﻿/*
____
 L|ypps Web controls for ASP.NET

Copyright (c) 2009 Alessandro Zifiglio, http://www.Typps.com
EMail: alessandro@Typps.com

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
namespace Typps
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Configuration;
    using System.Data;
    using System.Drawing;
    using System.Drawing.Design;
    using System.Globalization;
    using System.IO;
    using System.Reflection;
    using System.Resources;
    using System.Text;
    using System.Threading;
    using System.Web;
    using System.Web.Hosting;
    using System.Web.Script.Serialization;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Xml;

    [ToolboxBitmap(typeof(ResourceDummy), "Typps.Resources.Images.mediaframe.bmp")]
    [DefaultProperty("TargetControlImageUrl")]
    [Designer(typeof(Typps.MediaFrameDesigner))]
    [ToolboxData("<{0}:MediaFrame runat=\"server\"></{0}:MediaFrame>")]
    public class MediaFrame : DataBoundControlBase
    {
        #region Fields

        ClientScriptManager cs;
        string[] _commonCssImageList = new string[] { "tristatebutton80x33.gif", "tristatebutton110x33.gif", "tristatebutton200x33.gif", "tristateclosebutton16x48.gif" };
        string _cssKey = "Typps.MediaFrame";
        UpdatePanelProgress _embeddedUpdatePanelProgress;
        string _keyFormat = "MediaFrame_{0}";
        private MediaFrameCollection _mediaItems = null;
        System.Web.UI.WebControls.Image _popperImage = null;
        string _rootImageSkinFolder = "Typps.Resources.Skins.{0}.Images.MediaFrame.{1}";
        string _rootSkinFolder = "Typps.Resources.Skins.{0}.{1}";
        string _rootTemplateSkinFolder = "Typps.Resources.Skins.{0}.Templates.{1}";
        string _styleSheetName = "Css.mediaframe.css";
        private MediaFrameThumbnailCollection _thumbnails = null;
        Color _updateProgressBackgroundColor = Color.Black;
        int _updateProgressTransparency = 20;
        private string _webResponseData = string.Empty;

        #endregion Fields

        #region Constructors

        public MediaFrame()
            : base()
        {
        }

        #endregion Constructors

        #region Events

        //Invoke delegates registered with the Click event.
        public event ColorSelectionEventHandler ColorSelectionChanged;

        #endregion Events

        #region Properties

        [DefaultValue(true),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public bool AllowNavigation
        {
            get
            {
                return (ViewState["AllowNavigation"] == null) ?
                    true : (bool)ViewState["AllowNavigation"];
            }
            set
            {
                ViewState["AllowNavigation"] = value;
            }
        }

        [DefaultValue(true),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public bool AllowPaging
        {
            get
            {
                return (ViewState["AllowPaging"] == null) ?
                    true : (bool)ViewState["AllowPaging"];
            }
            set
            {
                ViewState["AllowPaging"] = value;
            }
        }

        [DefaultValue(true),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public bool AllowSlideShow
        {
            get
            {
                return (ViewState["AllowSlideShow"] == null) ?
                   true : (bool)ViewState["AllowSlideShow"];
            }
            set
            {
                ViewState["AllowSlideShow"] = value;
            }
        }

        /// <summary>
        /// Auto starts the slide show when the targetcontrol is activated. 
        /// The default is false.
        /// </summary>
        [DefaultValue(false),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public bool AutoStartSlideShow
        {
            get
            {
                return (bool)(ViewState["AutoStartSlideShow"] ?? false);
            }
            set
            {
                ViewState["AutoStartSlideShow"] = value;
            }
        }

        [DefaultValue(typeof(CssFloatStyle), "Left"),
        Description("Float from left to right ? Or right to left."),
        Category("Appearance"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public CssFloatStyle CssFloat
        {
            get { return (ViewState["CssFloat"] == null) ? CssFloatStyle.Left : (CssFloatStyle)ViewState["CssFloat"]; }
            set { ViewState["CssFloat"] = value; }
        }

        /// <summary>
        /// Gets/Sets a position value indicating whether the mediaframe is 
        /// displayed in an absolutely positioned modal popup or positioned
        /// within the page flow (no modalpopup). By default it is positioned
        /// in a modal popup.
        /// </summary>
        [DefaultValue(typeof(Position), "ModalPopup"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public Position Display
        {
            get
            {
                return (ViewState["Display"] == null) ?
                    Position.ModalPopup : (Position)ViewState["Display"];
            }
            set
            {
                ViewState["Display"] = value;
            }
        }

        /// <summary>
        /// Gets/Sets a value indicating the header area holding
        /// the title should display or not? The default is true.
        /// </summary>
        [DefaultValue(true),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public bool DisplayHeader
        {
            get
            {
                return (ViewState["DisplayHeader"] == null) ?
                    true : (bool)ViewState["DisplayHeader"];
            }
            set
            {
                ViewState["DisplayHeader"] = value;
            }
        }

        /// <summary>
        /// Gets/Sets a value indicating whether a loading status label
        /// is displayed when preloading the next frame while the current 
        /// one is in view. By default this is true.
        /// </summary>
        [DefaultValue(true),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public bool DisplayLoadingStatus
        {
            get
            {
                return (ViewState["DisplayLoadingStatus"] == null) ?
                    true : (bool)ViewState["DisplayLoadingStatus"];
            }
            set
            {
                ViewState["DisplayLoadingStatus"] = value;
            }
        }

        /// <summary>
        /// By default, when an image is too large to fit in the screen, it is clipped.
        /// You can control this behavior via the LargeMediaItem property. When the element
        /// is clipped to fit in the viewport, and dragging is enabled, the drag speed by
        /// default is the normal speed the end user drags his mouse. This might be too speedy
        /// and because of that DragSpeed allows you to manually set the speed. Try increments of
        /// 5 and set it to what you feel is variably a good drag speed.
        /// </summary>
        [DefaultValue(0),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public int DragSpeed
        {
            get
            {
                return (int)(ViewState["DragSpeed"] ?? 0);
            }
            set
            {
                ViewState["DragSpeed"] = value;
            }
        }

        [PersistenceMode(PersistenceMode.InnerProperty),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public UpdatePanelProgress EmbeddedUpdatePanelProgress
        {
            get
            {
                if (_embeddedUpdatePanelProgress == null)
                    _embeddedUpdatePanelProgress = new UpdatePanelProgress();
                return _embeddedUpdatePanelProgress;
            }
        }

        /// <summary>
        /// Gets/Sets a value that enables transitione effects on the slides as they come in and go out of view.
        /// Default is true.
        /// </summary>
        [DefaultValue(true),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public bool EnableEffects
        {
            get
            {
                return (bool)(ViewState["EnableEffects"] ?? true);
            }
            set
            {
                ViewState["EnableEffects"] = value;
            }
        }

        /// <summary>
        /// The minimum Height of the box frame. You can't make it any lower than this. 
        /// You can however provide a larger value
        /// </summary>
        [DefaultValue(typeof(Unit), "30px"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public Unit FloatingNavigatorHeight
        {
            get
            {
                return (Unit)(ViewState["FloatingNavigatorHeight"] ?? new Unit(30, UnitType.Pixel));
            }
            set
            {
                ViewState["FloatingNavigatorHeight"] = value;
            }
        }

        /// <summary>
        /// When a media item such as an image is too large to fit in the current window,
        /// it will become draggable by default. This means you can click the element and
        /// drag it to view the remaining areas not yet visible in the client viewport.
        /// Set to SqueezeToFit, if you'd rather the image was squeezed to fit the viewport.
        /// </summary>
        [DefaultValue(typeof(MediaItemOverflow), "AllowDrag"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public MediaItemOverflow LargeMediaItem
        {
            get
            {
                return (MediaItemOverflow)(ViewState["LargeMediaItem"] ??
                    MediaItemOverflow.AllowDrag);
            }
            set
            {
                ViewState["LargeMediaItem"] = value;
            }
        }

        /// <summary>
        /// The url to a default media to display in case the original intended media load fails.
        /// </summary>
        [DefaultValue("")]
        [Editor(typeof(System.Web.UI.Design.UrlEditor), typeof(UITypeEditor)),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string LoadFailureMediaUrl
        {
            get
            {
                return (string)(ViewState["LoadFailureMediaUrl"] ?? string.Empty);
            }
            set
            {
                ViewState["LoadFailureMediaUrl"] = value;
            }
        }

        /// <summary>
        /// The loading error message displayed when loading the media fails.
        /// </summary>
        [DefaultValue("Failed to load ..."),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string LoadFailureMessage
        {
            get
            {
                return (string)(ViewState["LoadFailureMessage"] ?? GetLocalizedText("LoadFailure"));
            }
            set
            {
                ViewState["LoadFailureMessage"] = value;
            }
        }

        /// <summary>
        /// The message displayed when loading the media is in progress.
        /// </summary>
        [DefaultValue(""),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string LoadingMessage
        {
            get
            {
                return (string)(ViewState["LoadingMessage"] ?? string.Empty);
            }
            set
            {
                ViewState["LoadingMessage"] = value;
            }
        }

        /// <summary>
        /// Control is initialized manually by a call clientside via
        /// initializeRequest(). In order to do this, you need to use
        /// $find() first and then call the initializeRequest method in it.
        /// </summary>
        [DefaultValue(false),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public bool ManuallyInitialize
        {
            get { return (ViewState["ManuallyInitialize"] == null) ? false : (bool)ViewState["ManuallyInitialize"]; }
            set { ViewState["ManuallyInitialize"] = value; }
        }

        /// <summary>
        /// The media type contained in MediaItems. Either they are image or
        /// video files example youtube video, google videos etc..
        /// </summary>
        [DefaultValue(typeof(MediaType), "Images"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public MediaType MediaDisplayMode
        {
            get
            {
                return (ViewState["MediaDisplayMode"] == null) ?
                    MediaType.Images : (MediaType)ViewState["MediaDisplayMode"];
            }
            set
            {
                ViewState["MediaDisplayMode"] = value;
            }
        }

        [DefaultValue("Loading Media frame ..."),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string MediaFrameLoadingMessage
        {
            get { return (ViewState["MediaFrameLoadingMessage"] == null) ? GetLocalizedText("LoadingMessage") : ViewState["MediaFrameLoadingMessage"].ToString(); }
            set { ViewState["MediaFrameLoadingMessage"] = value; }
        }

        [Category("Behavior"),
        Description("A collection of MediaItems "),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        Editor(typeof(Typps.MediaFrameCollectionEditor),
            typeof(System.Drawing.Design.UITypeEditor)),
        PersistenceMode(PersistenceMode.InnerProperty),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public MediaFrameCollection MediaItems
        {
            get
            {
                if (_mediaItems == null)
                    _mediaItems = new MediaFrameCollection();
                if (IsTrackingViewState)
                {
                    ((IStateManager)(_mediaItems)).TrackViewState();
                }
                return _mediaItems;
            }
        }

        [DefaultValue(""),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string MediaItemTitleField
        {
            get
            {
                return (string)(ViewState["MediaItemTitleField"] ?? string.Empty);
            }
            set
            {
                ViewState["MediaItemTitleField"] = value;
                if (Initialized)
                {
                    OnDataPropertyChanged();
                }
            }
        }

        [DefaultValue("{0}"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string MediaItemTitleFieldFormatString
        {
            get
            {
                return (string)(ViewState["MediaItemTitleFieldFormatString"] ?? "{0}");
            }
            set
            {
                ViewState["MediaItemTitleFieldFormatString"] = value;
            }
        }

        [DefaultValue(""),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string MediaItemUrlField
        {
            get
            {
                return (string)(ViewState["MediaItemUrlField"] ?? string.Empty);
            }
            set
            {
                ViewState["MediaItemUrlField"] = value;
                if (Initialized)
                {
                    OnDataPropertyChanged();
                }
            }
        }

        [DefaultValue("{0}"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string MediaItemUrlFieldFormatString
        {
            get
            {
                return (string)(ViewState["MediaItemUrlFieldFormatString"] ?? "{0}");
            }
            set
            {
                ViewState["MediaItemUrlFieldFormatString"] = value;
            }
        }

        [DefaultValue(""),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string MediaItemValueField
        {
            get
            {
                return (string)(ViewState["MediaItemValueField"] ?? string.Empty);
            }
            set
            {
                ViewState["MediaItemValueField"] = value;
                if (Initialized)
                {
                    OnDataPropertyChanged();
                }
            }
        }

        /// <summary>
        /// The minimum Height of the shadow box frame holding the media item
        /// </summary>
        [DefaultValue(300),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public int MinFrameHeight
        {
            get
            {
                return (int)(ViewState["MinFrameHeight"] ?? 300);
            }
            set
            {
                ViewState["MinFrameHeight"] = value;
            }
        }

        /// <summary>
        /// The minimum Width of the shadow box holding the media item
        /// </summary>
        [DefaultValue(300),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public int MinFrameWidth
        {
            get
            {
                return (int)(ViewState["MinFrameWidth"] ?? 300);
            }
            set
            {
                ViewState["MinFrameWidth"] = value;
            }
        }

        [DefaultValue("More"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string MoreButtonTitle
        {
            get { return (ViewState["MoreButtonTitle"] == null) ? GetLocalizedText("MoreButtonTitle") : ViewState["MoreButtonTitle"].ToString(); }
            set { ViewState["MoreButtonTitle"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientBeginWebRequest
        {
            get { return (ViewState["OnClientBeginWebRequest"] == null) ? string.Empty : (string)ViewState["OnClientBeginWebRequest"]; }
            set { ViewState["OnClientBeginWebRequest"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientEndWebRequest
        {
            get { return (ViewState["OnClientEndWebRequest"] == null) ? string.Empty : (string)ViewState["OnClientEndWebRequest"]; }
            set { ViewState["OnClientEndWebRequest"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientFirstButtonClicked
        {
            get { return (ViewState["OnClientFirstButtonClicked"] == null) ? string.Empty : (string)ViewState["OnClientFirstButtonClicked"]; }
            set { ViewState["OnClientFirstButtonClicked"] = value; }
        }

        /// <summary>
        /// Fires when the loading status label is hidden
        /// </summary>
        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientHideLoadingStatus
        {
            get { return (ViewState["OnClientHideLoadingStatus"] == null) ? string.Empty : (string)ViewState["OnClientHideLoadingStatus"]; }
            set { ViewState["OnClientHideLoadingStatus"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientLastButtonClicked
        {
            get { return (ViewState["OnClientLastButtonClicked"] == null) ? string.Empty : (string)ViewState["OnClientLastButtonClicked"]; }
            set { ViewState["OnClientLastButtonClicked"] = value; }
        }

        /// <summary>
        /// Fired when an image element is clicked 
        /// clientside ( currently only image elements fire this handler)
        /// </summary>
        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientMediaElementClicked
        {
            get { return (ViewState["OnClientMediaElementClicked"] == null) ? string.Empty : (string)ViewState["OnClientMediaElementClicked"]; }
            set { ViewState["OnClientMediaElementClicked"] = value; }
        }

        /// <summary>
        /// Fired when an image element completes loading 
        /// clientside ( currently only image elements fire this handler)
        /// </summary>
        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientMediaElementLoaded
        {
            get { return (ViewState["OnClientMediaElementLoaded"] == null) ? string.Empty : (string)ViewState["OnClientMediaElementLoaded"]; }
            set { ViewState["OnClientMediaElementLoaded"] = value; }
        }

        /// <summary>
        /// Fired when an image element loads but fails
        /// most likely due to the resource not being found
        /// </summary>
        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientMediaElementOnLoadError
        {
            get { return (ViewState["OnClientMediaElementOnLoadError"] == null) ? string.Empty : (string)ViewState["OnClientMediaElementOnLoadError"]; }
            set { ViewState["OnClientMediaElementOnLoadError"] = value; }
        }

        /// <summary>
        /// Register to this clientside event handler if you want to provide some special effects to the
        /// currently displayed clip, eg : how a clip slides into view etc
        /// </summary>
        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientMediaItemDisplay
        {
            get { return (ViewState["OnClientMediaItemDisplay"] == null) ? string.Empty : (string)ViewState["OnClientMediaItemDisplay"]; }
            set { ViewState["OnClientMediaItemDisplay"] = value; }
        }

        /// <summary>
        /// Register to this clientside event handler if you want notification when a MediaItem is displayed.
        /// This is very similar to OnClientMediaItemDisplay as they are both fired during the same interval
        /// and their event arguments have the same information. The main difference is on the purpose. Use
        /// OnClientMediaItemDisplay when you want to apply special effects to a clip, as execution comes
        /// to a halt when this handler fires allowing you to handle the display manually. 
        /// Use OnClientMediaItemShow when you need only a notification, but after that 
        /// you want mediaframe to go on doing what it does (execution does not come to a halt after this handler
        /// is fired). Also another notable difference is that OnClientMediaItemShow fires before OnClientMediaItemDisplay.
        /// </summary>
        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientMediaItemShow
        {
            get { return (ViewState["OnClientMediaItemShow"] == null) ? string.Empty : (string)ViewState["OnClientMediaItemShow"]; }
            set { ViewState["OnClientMediaItemShow"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientNextButtonClicked
        {
            get { return (ViewState["OnClientNextButtonClicked"] == null) ? string.Empty : (string)ViewState["OnClientNextButtonClicked"]; }
            set { ViewState["OnClientNextButtonClicked"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientPagerButtonClicked
        {
            get { return (ViewState["OnClientPagerButtonClicked"] == null) ? string.Empty : (string)ViewState["OnClientPagerButtonClicked"]; }
            set { ViewState["OnClientPagerButtonClicked"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientPauseButtonClicked
        {
            get { return (ViewState["OnClientPauseButtonClicked"] == null) ? string.Empty : (string)ViewState["OnClientPauseButtonClicked"]; }
            set { ViewState["OnClientPauseButtonClicked"] = value; }
        }

        /// <summary>
        /// Fired when an image element is loaded in the background
        /// </summary>
        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientPreload
        {
            get { return (ViewState["OnClientPreload"] == null) ? string.Empty : (string)ViewState["OnClientPreload"]; }
            set { ViewState["OnClientPreload"] = value; }
        }

        /// <summary>
        /// Fired when an image element is loaded in the background
        /// but fails most likely due to the resource not being found
        /// </summary>
        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientPreloadOnError
        {
            get { return (ViewState["OnClientPreloadOnError"] == null) ? string.Empty : (string)ViewState["OnClientPreloadOnError"]; }
            set { ViewState["OnClientPreloadOnError"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientPreviousButtonClicked
        {
            get { return (ViewState["OnClientPreviousButtonClicked"] == null) ? string.Empty : (string)ViewState["OnClientPreviousButtonClicked"]; }
            set { ViewState["OnClientPreviousButtonClicked"] = value; }
        }

        /// <summary>
        /// Fires when the loading status label is absolutely repositioned within the 
        /// content area of the display region
        /// </summary>
        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientRepositionLoadingStatus
        {
            get { return (ViewState["OnClientRepositionLoadingStatus"] == null) ? string.Empty : (string)ViewState["OnClientRepositionLoadingStatus"]; }
            set { ViewState["OnClientRepositionLoadingStatus"] = value; }
        }

        /// <summary>
        /// Fires when the loading status label is displayed
        /// </summary>
        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientShowLoadingStatus
        {
            get { return (ViewState["OnClientShowLoadingStatus"] == null) ? string.Empty : (string)ViewState["OnClientShowLoadingStatus"]; }
            set { ViewState["OnClientShowLoadingStatus"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientSlideShowButtonClicked
        {
            get { return (ViewState["OnClientSlideShowButtonClicked"] == null) ? string.Empty : (string)ViewState["OnClientSlideShowButtonClicked"]; }
            set { ViewState["OnClientSlideShowButtonClicked"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientTargetControlAction
        {
            get { return (ViewState["OnClientTargetControlAction"] == null) ? string.Empty : (string)ViewState["OnClientTargetControlAction"]; }
            set { ViewState["OnClientTargetControlAction"] = value; }
        }

        [DefaultValue(""),
        Category("ClientSide Events"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string OnClientThumbnailClicked
        {
            get { return (ViewState["OnClientThumbnailClicked"] == null) ? string.Empty : (string)ViewState["OnClientThumbnailClicked"]; }
            set { ViewState["OnClientThumbnailClicked"] = value; }
        }

        [DefaultValue(3),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public int PageSize
        {
            get
            {
                return (ViewState["PageSize"] == null) ?
                    3 : (int)ViewState["PageSize"];
            }
            set
            {
                ViewState["PageSize"] = value;
            }
        }

        /// <summary>
        /// When PreloadAll is true, all images are preloaded in the background.
        /// The default is false. By default, only the next image in sequence is preloaded in the
        /// background while previewing the current image. When setting PreloadAll to true,
        /// you can refine your control on the preload order by setting a priority value on each
        /// MediaItem instance which exposes a priority property and further allows you to set preload
        /// at the image level. By default when PreloadAll is true, all Media items have their preload
        /// set to true.
        /// </summary>
        [DefaultValue(false),
        NotifyParentProperty(true)]
        public bool PreloadAll
        {
            get
            {
                return (ViewState["PreloadAll"] == null) ?
                    false : (bool)ViewState["PreloadAll"];
            }
            set
            {
                ViewState["PreloadAll"] = value;
            }
        }

        /// <summary>
        /// When true the control will try to resgister the css required by this control.
        /// The default is true. When this control is consumed by the HTML Editor, it's set to
        /// false unless an external stylesheet is referenced by the Embedded instance of this control.
        /// This property is useful for control developers and not for use in user code.
        /// </summary>
        [Browsable(false),
        DefaultValue(true)]
        public virtual bool RegisterCSS
        {
            get
            {
                return (bool)(ViewState["RegisterCSS"] ?? true);
            }
            set
            {
                ViewState["RegisterCSS"] = value;
            }
        }

        [DefaultValue(typeof(Color), ""),
        Description("The shaded shadow cast when showing the editors dialog window"),
        TypeConverter(typeof(WebColorConverter)),
        Category("Appearance"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public Color ShaderColor
        {
            get { return (ViewState["ShaderColor"] == null) ? Color.Empty : (Color)ViewState["ShaderColor"]; }
            set { ViewState["ShaderColor"] = value; }
        }

        [DefaultValue(90),
        Description("The shaded shadow's opacity cast when showing the editors dialog window"),
        Category("Appearance"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public int ShaderOpacity
        {
            get { return (ViewState["ShaderOpacity"] == null) ? 90 : (int)ViewState["ShaderOpacity"]; }
            set { ViewState["ShaderOpacity"] = value; }
        }

        /// <summary>
        /// Gets/Sets a value indicating whether content should slide horizontally or vertically 
        /// when EnableEffects is true. The default is false (a vertical slide)
        /// </summary>
        [DefaultValue(true),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public bool SlideEffectHorizontal
        {
            get
            {
                return (bool)(ViewState["SlideEffectHorizontal"] ?? true);
            }
            set
            {
                ViewState["SlideEffectHorizontal"] = value;
            }
        }

        /// <summary>
        /// The interval between a slide. The default is 5000(5seconds).
        /// </summary>
        [DefaultValue(5000),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public int SlideShowInterval
        {
            get
            {
                return (int)(ViewState["SlideShowInterval"] ?? 5000);
            }
            set
            {
                ViewState["SlideShowInterval"] = value;
            }
        }

        /// <summary>
        /// Control ClientID which will activate and launch the color pick on click (the default, unless TargetControlActivationOn is specified). This can very well be the id of an html element
        /// not necessarily a ServerSide control.
        /// </summary>
        [TypeConverter(typeof(AssociatedHyperLinkConverter)),
        IDReferenceProperty,
        Category("Behavior"),
        Themeable(false),
        DefaultValue(""),
        Description("Target Control"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string TargetControl
        {
            get
            {
                return (ViewState["TargetControl"] == null) ? string.Empty : (string)ViewState["TargetControl"];
            }
            set
            {
                this.ViewState["TargetControl"] = value;
            }
        }

        /// <summary>
        /// The event on which the TargetControl gets to activate and launch MediaFrame. The default is
        /// click.
        /// </summary>
        [DefaultValue(typeof(ClientEventType), "click"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public ClientEventType TargetControlActivationOn
        {
            get { return (ViewState["TargetControlActivationOn"] == null) ? ClientEventType.click : (ClientEventType)ViewState["TargetControlActivationOn"]; }
            set { (ViewState["TargetControlActivationOn"]) = value; }
        }

        /// <summary>
        /// Only takes effect if target control is not specified and ManuallyInitialize is false. When this
        /// condition is met, by default an image is used to popup the Color Picker
        /// </summary>
        [Editor(typeof(System.Web.UI.Design.ImageUrlEditor), typeof(UITypeEditor)),
        DefaultValue(""),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string TargetControlImageUrl
        {
            get { return (ViewState["TargetControlImageUrl"] == null) ? string.Empty : (string)ViewState["TargetControlImageUrl"]; }
            set { ViewState["TargetControlImageUrl"] = value; }
        }

        [DefaultValue(""),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string ThumbnailClientIdField
        {
            get
            {
                return (string)(ViewState["ThumbnailClientIdField"] ?? string.Empty);
            }
            set
            {
                ViewState["ThumbnailClientIdField"] = value;
                if (Initialized)
                {
                    OnDataPropertyChanged();
                }
            }
        }

        [Category("Behavior"),
        Description("A collection of MediaItems "),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
        Editor(typeof(Typps.MediaFrameThumbnailCollectionEditor),
            typeof(System.Drawing.Design.UITypeEditor)),
        PersistenceMode(PersistenceMode.InnerProperty),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public MediaFrameThumbnailCollection Thumbnails
        {
            get
            {
                if (_thumbnails == null)
                    _thumbnails = new MediaFrameThumbnailCollection();
                if (IsTrackingViewState)
                {
                    ((IStateManager)(_thumbnails)).TrackViewState();
                }
                return _thumbnails;
            }
        }

        [DefaultValue(""),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string ThumbnailValueField
        {
            get
            {
                return (string)(ViewState["ThumbnailValueField"] ?? string.Empty);
            }
            set
            {
                ViewState["ThumbnailValueField"] = value;
                if (Initialized)
                {
                    OnDataPropertyChanged();
                }
            }
        }

        [DefaultValue(""),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public string UpdatePanelProgressId
        {
            get { return (ViewState["UpdatePanelProgressId"] == null) ? string.Empty : (string)ViewState["UpdatePanelProgressId"]; }
            set { ViewState["UpdatePanelProgressId"] = value; }
        }

        [TypeConverter(typeof(WebColorConverter)),
        DefaultValue(typeof(Color), "black"),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public Color UpdateProgressBackgroundColor
        {
            get
            {
                if (_updateProgressBackgroundColor == Color.Empty)
                    _updateProgressBackgroundColor = Color.Black;
                return _updateProgressBackgroundColor;
            }
            set
            {
                _updateProgressBackgroundColor = value;
            }
        }

        [DefaultValue(20),
        NotifyParentProperty(true),
        RefreshProperties(RefreshProperties.Repaint)]
        public int UpdateProgressTransparency
        {
            get
            {
                return _updateProgressTransparency;
            }
            set
            {
                _updateProgressTransparency = value;
            }
        }

        protected override string ClassName
        {
            get
            {
                string cn = (this.CssClass != string.Empty) ? this.CssClass : this.ClientID;
                return cn+" mediaframe";
            }
        }

        protected override string CssKey
        {
            get { return _cssKey; }
        }

        protected override string KeyFormat
        {
            get { return _keyFormat; }
        }

        protected override bool RenderSharedStyles
        {
            get
            {
                if (Display == Position.Static)
                    return false;
                return true;
            }
        }

        protected override bool RenderTreeViewStyles
        {
            get { return false; }
        }

        protected override string RootImageSkinFolder
        {
            get
            {
                string url = _rootImageSkinFolder;
                if (IsCustomSkin)
                    url = Helper.GetPhysicalPathByResourceNamespace(url, this);
                return url;
            }
        }

        protected override string RootSkinFolder
        {
            get
            {
                string url = _rootSkinFolder;
                if (IsCustomSkin)
                    url = Helper.GetPhysicalPathByResourceNamespace(url, this);
                return url;
            }
        }

        protected override string RootTemplateSkinFolder
        {
            get
            {
                string url = _rootTemplateSkinFolder;
                if (IsCustomSkin)
                    url = Helper.GetPhysicalPathByResourceNamespace(url, this);
                return url;
            }
        }

        protected override string StartupCssStyleIdentifier
        {
            get { return "mf"; }
        }

        protected override string StyleSheetName
        {
            get { return _styleSheetName; }
        }

        protected override HtmlTextWriterTag TagKey
        {
            get
            {
                return HtmlTextWriterTag.Div;
            }
        }

        #endregion Properties

        #region Methods

        internal List<CallbackHandler> GetAsyncEvents()
        {
            List<CallbackHandler> handlerList = new List<CallbackHandler>();
            handlerList.Add(new CallbackHandler("mediaframe", "MediaFrameRequest", MediaFrameLoadingMessage));
            return handlerList;
        }

        internal virtual void OnColorSelectionChanged(ColorSelectionEventArgs e)
        {
            if (ColorSelectionChanged != null)
            {
                ColorSelectionChanged(this, e);
            }
        }

        internal virtual void OnMediaFrameRequest(EventArgs e)
        {
            string templateName = string.Format(RootTemplateSkinFolder,
            SelectedSkin, "MediaFrame.html");
            _webResponseData = this.GetTemplateData(templateName).Replace("controlID", ClassName);
        }

        internal virtual void RegisterAsyncEvents(ref ScriptControlDescriptor descriptor)
        {
            List<CallbackHandler> handlerList = GetAsyncEvents();
            descriptor.AddScriptProperty("callbacks",  ToJsonString(handlerList));
        }

        internal virtual void SetAllowNavigationDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("allowNavigation", AllowNavigation);
        }

        internal virtual void SetAllowPagingDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("allowPaging", AllowPaging);
        }

        internal virtual void SetAllowSlideShowDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("allowSlideShow", AllowSlideShow);
        }

        internal virtual void SetAutoStartSlideShowDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("autoStartSlideShow", AutoStartSlideShow);
        }

        //ToDO: make an interface with the 5 properties (including setup/finish) in shake object since
        //all objects share these properties. this will be the type for the effects
        //property we shall expose. user should be able to pass an effect to this property
        //and all should be good. below check setup/finish on this interface and add the event
        internal virtual void SetClientSideEventsDescriptor(ref ScriptControlDescriptor descriptor)
        {
            Dictionary<string, string> dic = new Dictionary<string, string>();
            dic.Add("targetControlClick", OnClientTargetControlAction);
            dic.Add("thumbnailItemClick", OnClientThumbnailClicked);
            dic.Add("beginWebRequest", OnClientBeginWebRequest);
            dic.Add("endWebRequest", OnClientEndWebRequest);
            dic.Add("firstButton", OnClientFirstButtonClicked);
            dic.Add("lastButton", OnClientLastButtonClicked);
            dic.Add("previousButton", OnClientPreviousButtonClicked);
            dic.Add("nextButton", OnClientNextButtonClicked);
            dic.Add("slideShowButton", OnClientSlideShowButtonClicked);
            dic.Add("pauseButton", OnClientPauseButtonClicked);
            dic.Add("onMediaItemDisplay", OnClientMediaItemDisplay);
            dic.Add("pagerButton", OnClientPagerButtonClicked);
            dic.Add("mediaElementClicked", OnClientMediaElementClicked);
            dic.Add("mediaElementLoaded", OnClientMediaElementLoaded);
            dic.Add("mediaElementOnLoadError", OnClientMediaElementOnLoadError);
            dic.Add("mediaPreload", OnClientPreload);
            dic.Add("mediaPreloadOnError", OnClientPreloadOnError);
            dic.Add("onShowLoadingStatus", OnClientShowLoadingStatus);
            dic.Add("onHideLoadingStatus", OnClientHideLoadingStatus);
            dic.Add("onRepositionLoadingStatus", OnClientRepositionLoadingStatus);

            foreach (string eventName in dic.Keys)
            {
                string val = dic[eventName];
                if (!string.IsNullOrEmpty(val))
                    descriptor.AddEvent(eventName, val);
            }
        }

        internal virtual void SetDisplayDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("display", Display);
        }

        internal virtual void SetDisplayHeaderDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("displayHeader", DisplayHeader);
        }

        internal virtual void SetDisplayLoadingStatusDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("displayLoadingStatus", DisplayLoadingStatus);
        }

        internal virtual void SetDragSpeedDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("dragSpeed", DragSpeed);
        }

        internal virtual void SetEnableEffectsDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("enableEffects", EnableEffects);
        }

        internal virtual void SetFloatingNavigatorHeightDescriptor(ref ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("floatingNavigatorHeight", FloatingNavigatorHeight.ToString());
        }

        internal virtual void SetFormElementIdDescriptor(ref ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("formElementId", Page.Form.ClientID);
        }

        internal virtual void SetGlobalClassNameDescriptor(ref ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("className", ClassName);
        }

        internal virtual void SetGrabbingCursorDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            string url = string.Format("Typps.Resources.Skins.{0}.Images.Shared.grabbingcur.ico", SelectedSkin);
            if (IsCustomSkin)
                url = Helper.GetPhysicalPathByResourceNamespace(url, this);

            string grabbingCursor = Helper.GetBackgroundImageUrl(this,url);

            descriptor.AddProperty("grabbingCursor", grabbingCursor);
        }

        internal virtual void SetGrabCursorDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            string url = string.Format("Typps.Resources.Skins.{0}.Images.Shared.grabcur.ico", SelectedSkin);
            if (IsCustomSkin)
                url = Helper.GetPhysicalPathByResourceNamespace(url, this);

            string grabCursor = Helper.GetBackgroundImageUrl(this,url);
            descriptor.AddProperty("grabCursor", grabCursor);
        }

        internal virtual void SetLargeMediaItemDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("largeMediaItem", LargeMediaItem);
        }

        internal virtual void SetLoadFailureMediaUrlDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            string url = LoadFailureMediaUrl;
            if (string.IsNullOrEmpty(url))
                url = Helper.GetBackgroundImageUrl(this,
                    string.Format(RootImageSkinFolder, SelectedSkin, "404.gif"));
            descriptor.AddProperty("loadFailureMediaUrl", url ?? string.Empty);
        }

        internal virtual void SetLoadFailureMessageDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("loadFailureMessage", LoadFailureMessage);
        }

        internal virtual void SetLoadingMessageDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            if(!string.IsNullOrEmpty(LoadingMessage))
                descriptor.AddProperty("loadingMessage", LoadingMessage);
        }

        internal virtual void SetMediaDisplayModeDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("mediaDisplayMode", MediaDisplayMode);
        }

        internal virtual void SetMediaItemsDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            for (int num1 = 0; num1 < MediaItems.Count; num1++)
            {
                MediaItem mi1 = MediaItems[num1];
                if (string.IsNullOrEmpty(mi1.Url) && !IsDesignMode)
                    throw new Exception(string.Format("MediaItem at index {0} does not have a valid Url specified, please provide one.", num1));
            }
            descriptor.AddScriptProperty("mediaItems", ToJsonString(MediaItems));
        }

        internal virtual void SetMinFrameHeightDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("minFrameHeight", MinFrameHeight);
        }

        internal virtual void SetMinFrameWidthDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("minFrameWidth", MinFrameWidth);
        }

        internal virtual void SetMoreButtonTitleDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("moreButtonTitle", MoreButtonTitle);
        }

        internal virtual void SetPageSizeDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("pageSize", PageSize);
        }

        internal virtual void SetPostbackAllFormDataDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("postbackAllFormData", PostbackAllFormData);
        }

        internal virtual void SetPreloadAllDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("preloadAll", PreloadAll);
        }

        internal virtual void SetShaderColorDescriptor(ref ScriptControlDescriptor descriptor)
        {
            if (ShaderColor != Color.Empty)
                descriptor.AddProperty("shaderColor", ColorTranslator.ToHtml(ShaderColor));
        }

        internal virtual void SetShaderOpacityDescriptor(ref ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("shaderOpacity", ShaderOpacity);
        }

        internal virtual void SetSlideEffectHorizontalDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("slideEffectHorizontal", SlideEffectHorizontal);
        }

        internal virtual void SetSlideShowIntervalDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("slideShowInterval", SlideShowInterval);
        }

        internal virtual void SetTargetControlDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            string id = string.Empty;
            if (TargetControl != string.Empty)
                id = TargetControl;
            else if (_popperImage != null)
                id = _popperImage.ClientID;
            if (id != string.Empty)
                descriptor.AddProperty("targetControlId", id);
        }

        internal virtual void SetTargetControlEventNameDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("targetControlActivationOn", TargetControlActivationOn.ToString());
        }

        internal virtual void SetThumbnailsDescriptor(ref  ScriptControlDescriptor descriptor)
        {
            for (int num1 = 0; num1 < Thumbnails.Count; num1++)
            {
                MediaItemThumbnail mi = Thumbnails[num1];
                if (string.IsNullOrEmpty(mi.ClientID) && !IsDesignMode)
                    throw new Exception(string.Format("Thumbnail at index {0} does not have a valid ClientID specified, please provide one.", num1));
                if (string.IsNullOrEmpty(mi.Value) && !IsDesignMode)
                    throw new Exception(string.Format("Thumbnail at index {0} does not have a valid Value specified, please provide one.", num1));
            }
            descriptor.AddScriptProperty("thumbnails",ToJsonString(Thumbnails));
        }

        internal virtual void SetUniqueIdDescriptor(ref ScriptControlDescriptor descriptor)
        {
            descriptor.AddProperty("uniqueId", this.UniqueID);
        }

        internal virtual void SetUpdatePanelProgressIdDescriptor(ref ScriptControlDescriptor descriptor)
        {
            string id = string.IsNullOrEmpty(UpdatePanelProgressId) ?
                EmbeddedUpdatePanelProgress.ClientID : UpdatePanelProgressId;
            descriptor.AddProperty("updatePanelProgressId", id);
        }

        protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            // override to disable
            if (this.ID != null)
                writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
            //if (this.ClassName != string.Empty)
            //    writer.AddAttribute("class", ClassName);
            if (Display == Position.ModalPopup)
                writer.AddStyleAttribute(HtmlTextWriterStyle.Display, "inline");
            string accessKey = this.AccessKey;
            if (accessKey.Length > 0)
                writer.AddAttribute(HtmlTextWriterAttribute.Accesskey, accessKey);
            if (!this.Enabled)
                writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
        }

        protected override void CreateChildControls()
        {
            if (!IsBrowserUpLevel) return;

            if (cs == null && Page != null)
                cs = Page.ClientScript;
            if (Display == Position.ModalPopup)
            {
                if (this.Thumbnails.Count != 0)
                    ManuallyInitialize = true;
                MediaFramePopper();
            }
            else
            {
                string templateName = string.Format(RootTemplateSkinFolder,
            SelectedSkin, "MediaFrame.html");
                string markup = this.GetTemplateData(templateName).Replace("controlID", ClassName);
                this.Controls.Add(new LiteralControl(markup));
            }
        }

        protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
        {
            ScriptControlDescriptor descriptor = new ScriptControlDescriptor("Typps.MediaFrame", this.ClientID);
            if (DesignMode)
                return new ScriptDescriptor[] { descriptor };
            SetGlobalClassNameDescriptor(ref descriptor);
            SetShaderColorDescriptor(ref descriptor);
            SetShaderOpacityDescriptor(ref descriptor);
            RegisterAsyncEvents(ref descriptor);
            SetClientSideEventsDescriptor(ref descriptor);
            SetTargetControlDescriptor(ref descriptor);
            SetTargetControlEventNameDescriptor(ref descriptor);
            SetUniqueIdDescriptor(ref descriptor);
            SetUpdatePanelProgressIdDescriptor(ref descriptor);
            SetEnableEffectsDescriptor(ref descriptor);
            SetFormElementIdDescriptor(ref descriptor);
            SetFloatingNavigatorHeightDescriptor(ref descriptor);
            SetPostbackAllFormDataDescriptor(ref descriptor);
            SetDisplayDescriptor(ref descriptor);
            SetPreloadAllDescriptor(ref descriptor);
            SetMediaItemsDescriptor(ref descriptor);
            SetThumbnailsDescriptor(ref descriptor);
            SetMediaDisplayModeDescriptor(ref descriptor);
            SetAllowNavigationDescriptor(ref descriptor);
            SetAllowPagingDescriptor(ref descriptor);
            SetAllowSlideShowDescriptor(ref descriptor);
            SetPageSizeDescriptor(ref descriptor);
            SetMoreButtonTitleDescriptor(ref descriptor);
            SetSlideShowIntervalDescriptor(ref descriptor);
            SetAutoStartSlideShowDescriptor(ref descriptor);
            SetLoadFailureMessageDescriptor(ref descriptor);
            SetLoadingMessageDescriptor(ref descriptor);
            SetLoadFailureMediaUrlDescriptor(ref descriptor);
            SetMinFrameWidthDescriptor(ref descriptor);
            SetMinFrameHeightDescriptor(ref descriptor);
            SetLargeMediaItemDescriptor(ref descriptor);
            SetDragSpeedDescriptor(ref descriptor);
            SetDisplayHeaderDescriptor(ref descriptor);
            SetDisplayLoadingStatusDescriptor(ref descriptor);
            SetGrabCursorDescriptor(ref descriptor);
            SetGrabbingCursorDescriptor(ref descriptor);
            SetSlideEffectHorizontalDescriptor(ref descriptor);
            return new ScriptDescriptor[] { descriptor };
        }

        protected override IEnumerable<ScriptReference> GetScriptReferences()
        {
            if (cs == null) return null;
            ScriptReference reference1 = new ScriptReference();
            bool isDebugMode = SM.ScriptMode == ScriptMode.Debug;
            string script1 = !isDebugMode ? "ClientScripts.startup.min.js" : "ClientScripts.startup.js";
            string script2 = !isDebugMode ? "ClientScripts.spryeffects.min.js" : "ClientScripts.spryeffects.js";
            string script3 = !isDebugMode ? "ClientScripts.mediaframe.min.js" : "ClientScripts.mediaframe.js";

            string startup = Helper.GetManifestResourceName(script1,
                ManifestResourceNamesCache, isDebugMode);

            reference1.Path = cs.GetWebResourceUrl(typeof(MediaFrame),
                startup);

            ScriptReference reference2 = new ScriptReference();
            reference2.Path = cs.GetWebResourceUrl(typeof(MediaFrame),
                Helper.GetManifestResourceName(script2,
                ManifestResourceNamesCache, isDebugMode));

            ScriptReference reference3 = new ScriptReference();
            reference3.Path = cs.GetWebResourceUrl(typeof(ResourceDummy),
                Helper.GetManifestResourceName(script3,
                ManifestResourceNamesCache, isDebugMode));

            return new ScriptReference[] { reference1, reference2, reference3};
        }

        protected override void LoadViewState(object state)
        {
            if (state != null)
            {
                object[] states = (object[])state;
                base.LoadViewState(states[0]);
                ((IStateManager)MediaItems).LoadViewState(states[1]);
                ((IStateManager)Thumbnails).LoadViewState(states[2]);
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            cs = Page.ClientScript;
            EnsureChildControls();
            if (!this.DesignMode)
            {
                EnsureScriptManager();
                RaiseCallbackEvent();
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            if (IsCallback) return;

            if (!this.DesignMode)
            {
                if (SM == null)
                    throw new HttpException("A ScriptManager control must exist on the current page.");

                SM.RegisterScriptControl(this);
            }
            if (RegisterCSS)
            {
                InitializeCSSRegistration();
            }
        }

        protected override void OnUnload(EventArgs e)
        {
            base.OnUnload(e);
            if (DesignMode) return;
            if (IsCallback)
            {
                if (!string.IsNullOrEmpty(CallbackArgument))
                {
                    ResponseWrite(string.Format("{0}$callbackdata${1}$sep${2}",
                        CallbackArgument, this.ClientID, _webResponseData), "text/plain");
                }
            }
        }

        protected override void PerformDataBinding(IEnumerable retrievedData)
        {
            base.PerformDataBinding(retrievedData);
            if (retrievedData != null)
            {
                foreach (object dataItem in retrievedData)
                {
                    MediaItemThumbnail mit = null;
                    MediaItem mi = null;
                    bool flag1 = false;
                    // The dataItem is not just a string, but potentially
                    // a System.Data.DataRowView or some other container.
                    // If the fields are set, use them to determine which
                    // field to render. Otherwise, use the first field.
                    if (ThumbnailClientIdField.Length > 0 && ThumbnailValueField.Length > 0)
                    {
                        flag1 = true;
                        mit = new MediaItemThumbnail();
                        mit.ClientID = DataBinder.GetPropertyValue(dataItem,
                            ThumbnailClientIdField, null);
                        mit.Value = DataBinder.GetPropertyValue(dataItem,
                           ThumbnailValueField, null);
                    }
                    if (MediaItemUrlField.Length > 0)
                    {
                        flag1 = true;
                        mi = new MediaItem();
                        mi.Url = DataBinder.GetPropertyValue(dataItem,
                            MediaItemTitleField, MediaItemTitleFieldFormatString);

                        if (MediaItemTitleField.Length > 0)
                        {
                            mi.Title = DataBinder.GetPropertyValue(dataItem,
                                MediaItemTitleField, MediaItemUrlFieldFormatString);
                        }

                        if (MediaItemValueField.Length > 0)
                        {
                            mi.Value = DataBinder.GetPropertyValue(dataItem,
                                MediaItemValueField, null);
                        }
                    }
                    if (!flag1)
                    {
                        PropertyDescriptorCollection props =
                            TypeDescriptor.GetProperties(dataItem);
                        if (props.Count >= 1)
                        {
                            string mitClientId = string.Empty;
                            string mitValue = string.Empty;
                            string miUrl = string.Empty;
                            string miTitle = string.Empty;
                            string miValue = string.Empty;
                            foreach (PropertyDescriptor pd in props)
                            {
                                string displayName = pd.DisplayName.ToLower();
                                switch (displayName)
                                {
                                    case "thumbnailclientid":
                                        mitClientId = (string)pd.GetValue(dataItem);
                                        break;
                                    case "thumbnailvalue":
                                        mitValue = (string)pd.GetValue(dataItem);
                                        break;
                                    case "url":
                                        miUrl = (string)pd.GetValue(dataItem);
                                        break;
                                    case "title":
                                        miTitle = (string)pd.GetValue(dataItem);
                                        break;
                                    case "value":
                                        miValue = (string)pd.GetValue(dataItem);
                                        break;
                                }
                            }

                            if (!string.IsNullOrEmpty(mitClientId) &&
                                !string.IsNullOrEmpty(mitValue))
                                mit = new MediaItemThumbnail(mitValue, mitClientId);

                            if (!string.IsNullOrEmpty(miUrl))
                                mi = new MediaItem(
                                    string.Format(MediaItemTitleFieldFormatString, miTitle),
                                    string.Format(MediaItemUrlFieldFormatString, miUrl),
                                    miValue);
                        }
                    }
                    if (mit != null)
                        Thumbnails.Add(mit);
                    if (mi != null)
                        MediaItems.Add(mi);
                }
            }
        }

        protected override void PerformSelect()
        {
            if (!IsBoundUsingDataSourceID)
                OnDataBinding(EventArgs.Empty);

            GetData().Select(CreateDataSourceSelectArguments(),
                OnDataSourceViewSelectCallback);

            // The PerformDataBinding method has completed.
            RequiresDataBinding = false;
            MarkAsDataBound();

            // Raise the DataBound event.
            OnDataBound(EventArgs.Empty);
        }

        protected override string QueryStringData(CssFile cssFileToRegister)
        {
            bool formatStyleSheet = SM.ScriptMode == ScriptMode.Debug;
            StringBuilder queryStrings = new StringBuilder(7);
            queryStrings.AppendFormat("&ctl={0}", (int)ControlName.MediaFrame);
            queryStrings.AppendFormat("&s={0}", (int)Skin);
            queryStrings.AppendFormat("&cs={0}", CustomSkin);
            queryStrings.AppendFormat("&csf={0}", CustomSkinFolder);
            queryStrings.AppendFormat("&cc={0}", ClassName);
            queryStrings.AppendFormat("&fcss={0}", formatStyleSheet);
            queryStrings.AppendFormat("&cssfile={0}", cssFileToRegister);

            return queryStrings.ToString();
        }

        protected override void Render(HtmlTextWriter writer)
        {
            if (IsCallback) return;
            if (base.DesignMode)
            {
                this.EnsureChildControls();
            }
            else
            {
                if (SM != null && SM.SupportsPartialRendering)
                {
                    SM.RegisterScriptDescriptors(this);
                    string disposeComponent = string.Format(@"$find('{0}').dispose();", this.ClientID);
                    //SM.RegisterDispose(this, disposeComponent);
                }
            }
            base.Render(writer);
        }

        protected override void ResetCollectionsAndStyles()
        {
        }

        protected override object SaveViewState()
        {
            object[] states = new object[3];
            states[0] = base.SaveViewState();
            states[1] = (_mediaItems != null) ? ((IStateManager)_mediaItems).SaveViewState() : null;
            states[2] = (_thumbnails != null) ? ((IStateManager)_thumbnails).SaveViewState() : null;
            return states;
        }

        protected override void TrackViewState()
        {
            base.TrackViewState();
            if (_mediaItems != null)
                ((IStateManager)_mediaItems).TrackViewState();
            if (_thumbnails != null)
                ((IStateManager)_thumbnails).TrackViewState();
        }

        void CreateUpdatePanelProgress(Control container)
        {
            EmbeddedUpdatePanelProgress.AttachToUpdatePanelEventHandlers = false;

                if (Skin != SkinNames.Classic && EmbeddedUpdatePanelProgress.Skin == SkinNames.Classic)
                    EmbeddedUpdatePanelProgress.Skin = Skin;

                if (!string.IsNullOrEmpty(CustomSkinFolder) && string.IsNullOrEmpty(EmbeddedUpdatePanelProgress.CustomSkinFolder))
                    EmbeddedUpdatePanelProgress.CustomSkinFolder = CustomSkinFolder;

                if (CustomSkin != "None" && EmbeddedUpdatePanelProgress.CustomSkin == "None")
                    EmbeddedUpdatePanelProgress.CustomSkin = CustomSkin;

                if (!string.IsNullOrEmpty(ExternalStyleSheet) ||
                  !string.IsNullOrEmpty(EmbeddedUpdatePanelProgress.ExternalStyleSheet))
                    EmbeddedUpdatePanelProgress.RegisterCSS = false;

                container.Controls.Add(EmbeddedUpdatePanelProgress);
        }

        private string ExtractPostbackData()
        {
            string key = string.Format("{0}${1}", UniqueID, "properties");
            string value = Context.Request.Form[key];
            if (!string.IsNullOrEmpty(value))
                return value;
            else
                return string.Empty;
        }

        private void MediaFramePopper()
        {
            if (TargetControl == string.Empty && !ManuallyInitialize)
            {
                _popperImage = new System.Web.UI.WebControls.Image();
                _popperImage.ID = "icon";
                string url = Helper.GetBackgroundImageUrl(this,
                    string.Format(RootImageSkinFolder, SelectedSkin, "mediaframe.gif"));

                if (TargetControlImageUrl != string.Empty)
                    url = ResolveClientUrl(TargetControlImageUrl);

                _popperImage.ImageUrl = url;
                _popperImage.Height = Unit.Parse("14px");
                _popperImage.Width = Unit.Parse("14px");
                _popperImage.Style["cursor"] = "pointer";
                _popperImage.EnableViewState = false;
                this.Controls.Add(_popperImage);
            }
            if (string.IsNullOrEmpty(UpdatePanelProgressId))
            {
                CreateUpdatePanelProgress(this);
                if (DesignMode)
                {
                    EmbeddedUpdatePanelProgress.Style["display"] = "none";
                }
            }
        }

        private void OnDataSourceViewSelectCallback(IEnumerable retrievedData)
        {
            if (IsBoundUsingDataSourceID)
                OnDataBinding(EventArgs.Empty);

            PerformDataBinding(retrievedData);
        }

        private void RaiseCallbackEvent()
        {
            if (string.IsNullOrEmpty(CallbackArgument))
                return;
            switch (CallbackArgument)
            {
                case "MediaFrameRequest":
                    OnMediaFrameRequest(new EventArgs());
                    break;
            }
        }

        #endregion Methods
    }
}